package cn.toutatis.sandbox.root.security.service;

import cn.toutatis.common.toolkit.ObjectToolkit;
import cn.toutatis.sandbox.root.security.authEntity.AccountEntity;
import cn.toutatis.sandbox.root.security.authEntity.InitEntity;
import cn.toutatis.sandbox.root.security.constant.AuthType;
import cn.toutatis.sandbox.root.security.constant.MessageType;
import cn.toutatis.sandbox.root.security.service.controller.AuthorityController;
import cn.toutatis.sandbox.root.security.service.mapper.SystemUserMapper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import static cn.toutatis.sandbox.root.security.constant.ValidationMessage.*;

/**
 * @author Toutatis_Gc
 */
@Service
public class SecurityAuthenticationService implements UserDetailsService {

    private ObjectToolkit objectToolkit = ObjectToolkit.getInstance();

    @Autowired
    HttpServletRequest httpServletRequest;

    @Autowired
    HttpSession session;

    @Autowired
    SystemUserMapper systemUserMapper;

    @Override
    public UserDetails loadUserByUsername(String identity) throws UsernameNotFoundException {
        if (objectToolkit.strNotBlank(identity)){
            JSONObject identJson = JSONObject.parseObject(identity);
            if (!identJson.isEmpty()){
                String  authType = identJson.getString("authType");
                AuthType type = AuthType.valueOf(authType);
                switch (type){
                    case ACCOUNT_CHECK:
                        String checkCode = identJson.getString("checkCode");
                        if (checkCodeEquals(checkCode)){
                            String account = identJson.getString("account");
                            AccountEntity accountEntity = systemUserMapper.getUser(account);
                            if (accountEntity == null){
                                throwInfo(USER_NOT_EXIST,MessageType.STRING);
                            }
                            assert accountEntity != null;
                            accountEntity.setUsername(accountEntity.getAccount());
                            accountEntity.setPassword(accountEntity.getSecret());
                            boolean isOpen = "SYS_OPEN_0000".equals(accountEntity.getStatus());
                            if (!isOpen){
                                throwInfo(USER_BANNED,MessageType.STRING);
                            }
                            accountEntity.setEnabled(isOpen);
                            accountEntity.setAccountNonExpired(true);
                            accountEntity.setAccountNonLocked(true);
                            accountEntity.setCredentialsNonExpired(true);
                            return accountEntity;
                        }else {
                            throwInfo(CHECK_CODE_ERROR,MessageType.STRING);
                        }
                    case THIRD:

                    case ACCOUNT_NORMAL:
                    default:
                        throwInfo(AUTH_NOT_FOUND,MessageType.STRING);
                }
            }else {
                throwInfo(PARAMETER_ERROR,MessageType.STRING);
            }
        }else {
            throwInfo(PARAMETER_NOT_FOUND,MessageType.STRING);
        }
        return new InitEntity();
    }

    private void throwInfo(String validationMessage,Object o, MessageType type){
        String message;
        switch (type){
            case JSON:
                message = JSON.toJSONString(validationMessage);
                break;
            default:
                message = validationMessage;
                break;
        }
        throwInfo(message,o);
    }

    private void throwInfo(String validationMessage,Object object){
        if (object != null){
            session.setAttribute(VALIDATION_SESSION_KEY,object);
        }
        throw new UsernameNotFoundException(validationMessage);
    }

    private boolean checkCodeEquals(String checkCode){
        if (objectToolkit.strIsBlank(checkCode)){
            return false;
        }
        String codeSessionKey = AuthorityController.CODE_SESSION_KEY;
        HttpSession session = httpServletRequest.getSession();
        String sessionCheckCode = (String) session.getAttribute(codeSessionKey);
        if (sessionCheckCode == null){
            return false;
        }
        session.removeAttribute(codeSessionKey);
        return sessionCheckCode.equalsIgnoreCase(checkCode);
    }
}
